package com.lzh.redis.util;

import com.lzh.redis.serializer.FastJsonRedisSerializer;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author zhehen.lu
 * @date 2025/9/6 11:27
 */
@Component
public class RedisUtil {
    private static final Logger log = LoggerFactory.getLogger(RedisUtil.class);
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public RedisUtil() {
    }

    public boolean hasKey(String key) {
        return this.redisTemplate.hasKey(key);
    }

    public boolean expire(String key, Long time) {
        try {
            if (time > 0L) {
                this.redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }

            return true;
        } catch (Exception e) {
            log.error("设置缓存过期时间失败");
            return false;
        }
    }

    public boolean delete(String key) {
        return this.redisTemplate.delete(key);
    }

    public Long delete(List<String> keyList) {
        return this.redisTemplate.delete(keyList);
    }

    public long getExpire(String key) {
        return this.redisTemplate.getExpire(key);
    }

    public boolean set(String key, Object value) {
        try {
            this.redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            log.error("设置缓存失败");
            return false;
        }
    }

    public boolean set(String key, Object value, Long time) {
        try {
            if (time > 0L) {
                this.redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                this.set(key, value);
            }

            return true;
        } catch (Exception e) {
            log.error("设置缓存失败");
            return false;
        }
    }

    public boolean setIfAbsent(String key, Object value) {
        try {
            return this.redisTemplate.opsForValue().setIfAbsent(key, value);
        } catch (Exception e) {
            log.error("设置缓存失败");
            return false;
        }
    }

    public boolean setIfAbsent(String key, Object value, long time) {
        try {
            return this.redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("设置缓存失败");
            return false;
        }
    }

    public Object get(String key) {
        return StringUtils.isEmpty(key) ? null : this.redisTemplate.opsForValue().get(key);
    }

    public Long incrBy(String key, Integer incr) {
        return this.redisTemplate.opsForValue().increment(key, incr.longValue());
    }

    public Long decBy(String key, Integer incr) {
        return this.redisTemplate.opsForValue().decrement(key, incr.longValue());
    }

    public List<Object> mGet(List<String> keys) {
        return this.redisTemplate.opsForValue().multiGet(keys);
    }

    public void mSet(Map<String, Object> values) {
        this.redisTemplate.opsForValue().multiSet(values);
    }

    public void mSet(Map<String, Object> values, Long time) {
        this.redisTemplate.opsForValue().multiSet(values);
    }

    public void hSet(String key, String hk, Object hv) {
        BoundHashOperations<String, Object, Object> operations = this.redisTemplate.boundHashOps(key);
        operations.put(hk, hv);
    }

    public void hmSet(String key, Map<String, String> map) {
        if (!CollectionUtils.isEmpty(map)) {
            if (StringUtils.isBlank(key)) {
                throw new IllegalArgumentException("不是有效的key");
            } else {
                this.redisTemplate.opsForHash().putAll(key, map);
            }
        }
    }

    public void hDelete(String key, Object... hks) {
        this.redisTemplate.opsForHash().delete(key, hks);
    }

    public Object hGet(String key, String hk) {
        return this.redisTemplate.opsForHash().get(key, hk);
    }

    public List<Object> hValues(String key) {
        return this.redisTemplate.opsForHash().values(key);
    }

    public Map<String, Object> hmGet(String key, List<String> hks) {
        List<Object> collect = (List)hks.stream().map((item) -> {
            return item;
        }).collect(Collectors.toList());
        List<Object> result = this.redisTemplate.opsForHash().multiGet(key, collect);
        HashMap<String, Object> map = new HashMap();
        int index = 0;
        Iterator iterator = hks.iterator();

        while(iterator.hasNext()) {
            String hk = (String)iterator.next();
            int tmp = index;
            if (result.get(index++) != null) {
                map.put(hk, result.get(tmp));
            }
        }

        return map;
    }

    public long hIncr(String key, String hk, Long incr) {
        return this.redisTemplate.opsForHash().increment(key, hk, incr);
    }

    public void zIncrBy(String key, String member, Double score) {
        this.redisTemplate.opsForZSet().incrementScore(key, member, score);
    }

    public void zIncrBy(String key, Integer member, Double score) {
        this.redisTemplate.opsForZSet().incrementScore(key, member, score);
    }

    public void zIncrBy(String key, Integer member, Integer score) {
        this.redisTemplate.opsForZSet().incrementScore(key, member, (double)score);
    }

    public Set<ZSetOperations.TypedTuple<Object>> zRevRangeWithScore(String key, Long start, Long end) {
        return this.redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
    }

    public Set<ZSetOperations.TypedTuple<Object>> zRevRangeWithScore(String key, Integer start, Integer end) {
        return this.redisTemplate.opsForZSet().reverseRangeWithScores(key, (long)start, (long)end);
    }

    public Long zRevRank(String key, String member) {
        return this.redisTemplate.opsForZSet().reverseRank(key, member);
    }

    public Long zRevRank(String key, Integer member) {
        return this.redisTemplate.opsForZSet().reverseRank(key, member);
    }

    public Double zScore(String key, Integer member) {
        return this.redisTemplate.opsForZSet().score(key, member);
    }

    public void zAdd(String key, Integer member, Integer score) {
        this.redisTemplate.opsForZSet().add(key, member, (double)score);
    }

    public Object lPop(String key) {
        return this.redisTemplate.opsForList().leftPop(key);
    }

    public boolean rPush(String key, Object value) {
        try {
            this.redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception E) {
            log.error("设置缓存失败");
            return false;
        }
    }

    public boolean rPush(String key, Object... value) {
        try {
            this.redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception E) {
            log.error("设置缓存失败");
            return false;
        }
    }

    public boolean rPush(String key, Collection value) {
        try {
            this.redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception E) {
            log.error("设置缓存失败");
            return false;
        }
    }

    public Long lLen(String key) {
        return this.redisTemplate.opsForList().size(key);
    }

    public List<Object> lRange(String key, long start, long end) {
        return this.redisTemplate.opsForList().range(key, start, end);
    }

    public boolean sAdd(String key, Object... value) {
        try {
            Long num = this.redisTemplate.opsForSet().add(key, value);
            log.info("加入成功数量：{}", num);
            return true;
        } catch (Exception E) {
            log.error("设置缓存失败");
            return false;
        }
    }

    public void sAdds(String key, List<Long> value) {
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        FastJsonRedisSerializer genericFastJsonRedisSerializer = new FastJsonRedisSerializer();
        this.redisTemplate.executePipelined((RedisCallback<?>) (connection) -> {
            connection.openPipeline();
            value.forEach((v) -> {
                connection.setCommands().sAdd(stringRedisSerializer.serialize(key), new byte[][]{genericFastJsonRedisSerializer.serialize(v)});
            });
            connection.close();
            return null;
        });
    }

    public boolean sisMember(String key, Object value) {
        return this.redisTemplate.opsForSet().isMember(key, value);
    }

    public Set<Object> sMembers(String key) {
        return this.redisTemplate.opsForSet().members(key);
    }

    public Long sCard(String key) {
        return this.redisTemplate.opsForSet().size(key);
    }

    public Object sPop(String key) {
        return this.redisTemplate.opsForSet().pop(key);
    }

    public Object sRandMember(String key) {
        return this.redisTemplate.opsForSet().randomMember(key);
    }

    public List<Object> sRandMember(String key, Integer count) {
        return this.redisTemplate.opsForSet().randomMembers(key, (long)count);
    }

    public Long sRem(String key, String value) {
        return this.redisTemplate.opsForSet().remove(key, new Object[]{value});
    }

    public Long sRem(String key, Object... value) {
        return this.redisTemplate.opsForSet().remove(key, value);
    }
}
